using System;

namespace RxHeat.Threading
{
    /// <summary>
    ///     Immutable type used in some observables helper to communicate asynchronous results and exceptions in case of errors
    /// </summary>
    /// <typeparam name="TResult">The type of the result.</typeparam>
    public class AysncResult<TResult>
    {
        private readonly Exception _errorException;
        private readonly bool _isFaulted;
        private readonly TResult _result;

        /// <summary>
        ///     Initializes a new instance of the <see cref="AysncResult{TResult}" /> class.
        /// </summary>
        /// <param name="errorException">The error exception.</param>
        public AysncResult(Exception errorException)
            : this(errorException, true, default(TResult))
        {
        }

        /// <summary>
        ///     Initializes a new instance of the <see cref="AysncResult{TResult}" /> class.
        /// </summary>
        /// <param name="result">The result.</param>
        public AysncResult(TResult result)
            : this(null, false, result)
        {
        }

        /// <summary>
        ///     Prevents a default instance of the <see cref="AysncResult{TResult}" /> class from being created.
        /// </summary>
        /// <param name="errorException">The error exception.</param>
        /// <param name="isFaulted">
        ///     if set to <c>true</c> [is faulted].
        /// </param>
        /// <param name="result">The result.</param>
        private AysncResult(Exception errorException, bool isFaulted, TResult result)
        {
            _errorException = errorException;
            _isFaulted = isFaulted;
            _result = result;
        }

        /// <summary>
        ///     Gets a value indicating whether this instance is faulted.
        /// </summary>
        /// <value>
        ///     <c>true</c> if this instance is faulted; otherwise, <c>false</c>.
        /// </value>
        public bool IsFaulted
        {
            get { return _isFaulted; }
        }

        /// <summary>
        ///     Gets the error exception.
        /// </summary>
        /// <value>
        ///     The error exception.
        /// </value>
        public Exception ErrorException
        {
            get { return _errorException; }
        }

        /// <summary>
        ///     Gets the result.
        /// </summary>
        /// <value>
        ///     The result.
        /// </value>
        public TResult Result
        {
            get { return _result; }
        }
    }
}